package com.zhou.system.management.security.listener;

import com.zhou.common.operator.log.core.constant.OperateActionEnum;
import com.zhou.common.operator.log.core.model.ClientInfo;
import com.zhou.common.operator.log.core.model.OperateLogInfo;
import com.zhou.common.operator.log.core.model.PrincipalInfo;
import com.zhou.common.operator.log.core.resolver.ClientInfoResolver;
import com.zhou.common.operator.log.core.service.OperateLogStorageService;
import com.zhou.system.management.security.model.MyUserDetails;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.Date;

/**
 * @author xianfeng
 * @date 2023/5/13 15:30
 */
@Slf4j
@Component
public class MyHttpSessionListener implements HttpSessionListener {

    @Resource
    private ClientInfoResolver clientInfoResolver;

    @Resource
    private OperateLogStorageService logService;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        log.info("sessionCreated={}", se);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        log.info("sessionDestroyed={}", se);
        HttpSession session = se.getSession();
        //todo 记录下线类型，被踢下线的，还是到期后自动下线的
        //更新最后一次访问时间
        try {
            if (isTimeout(se.getSession())) {
                SecurityContext securityContext = (SecurityContext) se.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
                if (securityContext == null || securityContext.getAuthentication() != null) {
                    MyUserDetails currentUser = (MyUserDetails) securityContext.getAuthentication().getPrincipal();
                    OperateLogInfo logInfo = new OperateLogInfo();
                    logInfo.setClientInfo(new ClientInfo());
                    logInfo.setAddTime(new Date());
                    PrincipalInfo principalInfo = new PrincipalInfo();
                    principalInfo.setUserId(currentUser.getUserId() + "");
                    principalInfo.setUserName(currentUser.getUsername());
                    principalInfo.setUserPhone(currentUser.getPhone());
                    principalInfo.setOrgId(currentUser.getCurrOrgId() + "");
                    principalInfo.setOrgName(currentUser.getCurrOrgName() + "");
                    logInfo.setPrincipal(principalInfo);
                    logInfo.setAction(OperateActionEnum.LOGOUT.getAction());
                    logInfo.setOperatingInstruction("登出成功:超时自动登出sessionId" + se.getSession().getId());
                    this.logService.append(logInfo);
                }
            } else {
                //todo 情况为手动无效session（除了一个用户同一台机器多次登录）
                SecurityContext securityContext = (SecurityContext) se.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
                if (securityContext != null && securityContext.getAuthentication() != null) {
                    MyUserDetails currentUser = (MyUserDetails) securityContext.getAuthentication().getPrincipal();
                    OperateLogInfo logInfo = new OperateLogInfo();
                    logInfo.setClientInfo(new ClientInfo());
                    logInfo.setAddTime(new Date());
                    PrincipalInfo principalInfo = new PrincipalInfo();
                    principalInfo.setUserId(currentUser.getUserId() + "");
                    principalInfo.setUserName(currentUser.getUsername());
                    principalInfo.setUserPhone(currentUser.getPhone());
                    principalInfo.setOrgId(currentUser.getCurrOrgId() + "");
                    principalInfo.setOrgName(currentUser.getCurrOrgName() + "");
                    logInfo.setPrincipal(principalInfo);
                    logInfo.setAction(OperateActionEnum.LOGOUT.getAction());
                    logInfo.setOperatingInstruction("登出成功:第二次覆盖第一次登录" + se.getSession().getId());
                    this.logService.append(logInfo);
                }
            }
        } catch (Exception e) {
            log.error("", e);
        }


    }

    private boolean isTimeout(HttpSession httpSession) {
        int maxInactiveInterval = httpSession.getMaxInactiveInterval();
        long timeNow = System.currentTimeMillis();
        long idleTimeInternal = timeNow - httpSession.getLastAccessedTime();
        if (maxInactiveInterval > 0) {
            int timeIdle = (int) (idleTimeInternal / 1000L);
            if (timeIdle >= maxInactiveInterval) {
                return true;
            }
        }
        return false;
    }
}
